/*
 * ImageAnnotationApp.java
 */

package imageannotation;

import IO.SegmentedImageLoader;
import Image.Annotater;
import Image.SegmentedImage;
import Image.segment.Segmenter;
import Training.TrainingData;
import java.io.File;
import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;

/**
 * The main class of the application.
 */
public class ImageAnnotationApp extends SingleFrameApplication {
	TrainingData trainingData = new TrainingData(this);
	ImageAnnotationView view = null;

    /**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
		view = new ImageAnnotationView(this);
        show(view);
    }

    /**
     * This method is to initialize the specified window by injecting resources.
     * Windows shown in our application come fully initialized from the GUI
     * builder, so this additional configuration is not needed.
     */
    @Override protected void configureWindow(java.awt.Window root) {
    }

    /**
     * A convenient static getter for the application instance.
     * @return the instance of ImageAnnotationApp
     */
    public static ImageAnnotationApp getApplication() {
        return Application.getInstance(ImageAnnotationApp.class);
    }

	/**
	 * Calls the {@link TrainingData#loadTrainingData(java.io.File)} method to
	 * load the training data
	 *
	 * @param imageFiles either an image file or directory, if a directory all images
	 *         in the directory will be loaded
	 */
	public void loadTrainingData(File trainingPath) {
		Segmenter.setSegWinPath(trainingPath);
		trainingData.loadTrainingData(trainingPath);
	}

	/**
	 * Calls the {@link TrainingData#loadTrainingData(java.io.File[])} method to
	 * load the training data
	 * 
	 * @param imageFiles an array of images to load
	 */
	public void loadTrainingData(File[] imageFiles) {
		if (imageFiles.length > 0) {
			Segmenter.setSegWinPath(imageFiles[0].getParentFile());
			trainingData.loadTrainingData(imageFiles);
		}
	}

	/**
	 * Called when the training data has finished loading in the worker thread
	 *
	 * @param loader should be an instance of {@link SegmentedImageLoader}
	 */
	public void trainingLoadFinished(Object loader) {
		if (loader instanceof SegmentedImageLoader) {
			view.showMessage("Training data loaded.");

			if (loader != null) {
				view.loadTrainingSetEnabled(false);
				view.openImageSetEnabled(true);
				trainingData.setImages(((SegmentedImageLoader)loader).getImages());
			}
		}
	}

	/**
	 * Calls the {@link SegmentedImageLoader} to load an image in a worker thread
	 * 
	 * @param imageFile the File object for the image to load
	 */
	public void annotateImage(File imageFile) {
		File[] f = {imageFile};

		SegmentedImageLoader sil = new SegmentedImageLoader(
			this, f, "annotateLoadFinished"
		);
		sil.execute();
	}

	/**
	 * Called by the {@link SegmentedImageLoader} after it finishes loading the segmented
	 * images.
	 *
	 * @param loader should be an instance of SegmentedImageLoader otherwise nothing is
	 *                done
	 */
	public void annotateLoadFinished(Object loader) {
		if (loader instanceof SegmentedImageLoader) {
			view.showMessage("Loaded image to annotate, annotating...");


			Annotater a = new Annotater(
				this, trainingData, ((SegmentedImageLoader) loader).getImages().get(0)
			);
			a.execute();
		}
	}

	/**
	 * Called by the {@link Annotater} when it finishes annotating an image
	 *
	 * @param image the annotated image
	 */
	public void annotationFinished(SegmentedImage image) {
		view.showMessage("Annotation finished.");

		view.setAnnotatedImage(image);
		for (String word : image.getWords()) {
			System.out.println(word);
		}
	}

	/**
	 * @return whether or not CV Scores should be used in the comparison of the unknown
	 * segment to the training segments.
	 */
	public boolean useCVScores() {
		return view.useCVScores();
	}

	/**
	 * @return whether or not thresholds should be used in the comparison of the unknown
	 * segment to the training segments.
	 */
	public boolean useThresholds() {
		return view.useThresholds();
	}

    /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
        launch(ImageAnnotationApp.class, args);
    }
}
